]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
ibusManager: Disable IBus input sources on password entries
authorTakao Fujiwara <tfujiwar@redhat.com>
Thu, 27 Nov 2014 08:23:01 +0000 (17:23 +0900)
committerRui Matos <tiagomatos@gmail.com>
Mon, 12 Jan 2015 15:13:45 +0000 (16:13 +0100)
Input method preedit text needs to be disabled on password entries
for security and usability reasons.
IBus 1.5.7 provides the signal set-content-type so that panel UIs can
handle these special purpose input entries:
https://github.com/ibus/ibus/commit/6ca5ddb302c9

Unfortunately IBus versions older than 1.5.10 have a bug which causes
spurious set-content-type emissions when switching input focus that
temporarily lose purpose and hints defeating its intended semantics
and confusing users. We thus don't use it in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=730628

js/misc/ibusManager.js
js/ui/status/keyboard.js

index 06d808d3f5d62135891ea33b6198b410c1f8f139..529352ab24e4f59d4a124266b2514a051aeb9712 100644 (file)
@@ -8,7 +8,7 @@ const Signals = imports.signals;
 
 try {
     var IBus = imports.gi.IBus;
-    _checkIBusVersion();
+    _checkIBusVersion(1, 5, 2);
     const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
 } catch (e) {
     var IBus = null;
@@ -17,11 +17,7 @@ try {
 
 let _ibusManager = null;
 
-function _checkIBusVersion() {
-    var requiredMajor = 1;
-    var requiredMinor = 5;
-    var requiredMicro = 2;
-
+function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
     if ((IBus.MAJOR_VERSION > requiredMajor) ||
         (IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION > requiredMinor) ||
         (IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION == requiredMinor &&
@@ -125,6 +121,16 @@ const IBusManager = new Lang.Class({
                                                          object_path: IBus.PATH_PANEL });
             this._candidatePopup.setPanelService(this._panelService);
             this._panelService.connect('update-property', Lang.bind(this, this._updateProperty));
+            try {
+                // IBus versions older than 1.5.10 have a bug which
+                // causes spurious set-content-type emissions when
+                // switching input focus that temporarily lose purpose
+                // and hints defeating its intended semantics and
+                // confusing users. We thus don't use it in that case.
+                _checkIBusVersion(1, 5, 10);
+                this._panelService.connect('set-content-type', Lang.bind(this, this._setContentType));
+            } catch (e) {
+            }
             // If an engine is already active we need to get its properties
             this._ibus.get_global_engine_async(-1, null, Lang.bind(this, function(i, result) {
                 let engine;
@@ -174,6 +180,10 @@ const IBusManager = new Lang.Class({
         this.emit('property-updated', this._currentEngineName, prop);
     },
 
+    _setContentType: function(panel, purpose, hints) {
+        this.emit('set-content-type', purpose, hints);
+    },
+
     activateProperty: function(key, state) {
         this._panelService.property_activate(key, state);
     },
@@ -186,7 +196,10 @@ const IBusManager = new Lang.Class({
     },
 
     setEngine: function(id, callback) {
-        if (!IBus || !this._ready || id == this._currentEngineName) {
+        // Send id even if id == this._currentEngineName
+        // because 'properties-registered' signal can be emitted
+        // while this._ibusSources == null on a lock screen.
+        if (!IBus || !this._ready) {
             if (callback)
                 callback();
             return;
index 897497a5498217a00f21c929a465a42b6ffc0e59..3595a39d0a8d0aa307d0a5da3686005b63b333b7 100644 (file)
@@ -155,6 +155,7 @@ const InputSourceManager = new Lang.Class({
         this._ibusSources = {};
 
         this._currentSource = null;
+        this._backupSource = null;
 
         // All valid input sources currently in the gsettings
         // KEY_INPUT_SOURCES list ordered by most recently used
@@ -183,6 +184,7 @@ const InputSourceManager = new Lang.Class({
         this._ibusManager.connect('ready', Lang.bind(this, this._ibusReadyCallback));
         this._ibusManager.connect('properties-registered', Lang.bind(this, this._ibusPropertiesRegistered));
         this._ibusManager.connect('property-updated', Lang.bind(this, this._ibusPropertyUpdated));
+        this._ibusManager.connect('set-content-type', Lang.bind(this, this._ibusSetContentType));
 
         global.display.connect('modifiers-accelerator-activated', Lang.bind(this, this._modifiersSwitcher));
 
@@ -192,6 +194,7 @@ const InputSourceManager = new Lang.Class({
         this._overviewHiddenId = 0;
         this._settings.connect('changed::per-window', Lang.bind(this, this._sourcesPerWindowChanged));
         this._sourcesPerWindowChanged();
+        this._disableIBus = false;
     },
 
     reload: function() {
@@ -309,6 +312,8 @@ const InputSourceManager = new Lang.Class({
                 [exists, displayName, shortName, , ] =
                     this._xkbInfo.get_layout_info(id);
             } else if (type == INPUT_SOURCE_TYPE_IBUS) {
+                if (this._disableIBus)
+                    continue;
                 let engineDesc = this._ibusManager.getEngineDesc(id);
                 if (engineDesc) {
                     let language = IBus.get_language_name(engineDesc.get_language());
@@ -379,8 +384,20 @@ const InputSourceManager = new Lang.Class({
         }
         this._mruSources = mruSources.concat(sourcesList);
 
-        if (this._mruSources.length > 0)
+        if (this._mruSources.length > 0) {
+            if (!this._disableIBus && this._backupSource) {
+                for (let i = 0; i < this._mruSources.length; i++) {
+                    if (this._mruSources[i].type == this._backupSource.type &&
+                        this._mruSources[i].id == this._backupSource.id) {
+                        let currentSource = this._mruSources.splice(i, 1);
+                        this._mruSources = currentSource.concat(this._mruSources);
+                        break;
+                    }
+                }
+                this._backupSource = null;
+            }
             this._mruSources[0].activate();
+        }
 
         // All ibus engines are preloaded here to reduce the launching time
         // when users switch the input sources.
@@ -437,6 +454,27 @@ const InputSourceManager = new Lang.Class({
         return false;
     },
 
+    _ibusSetContentType: function(im, purpose, hints) {
+        if (purpose == IBus.InputPurpose.PASSWORD) {
+            if (Object.keys(this._inputSources).length == Object.keys(this._ibusSources).length)
+                return;
+
+            if (this._disableIBus)
+                return;
+            this._disableIBus = true;
+            this._backupSource = this._currentSource;
+        } else {
+            if (!this._disableIBus)
+                return;
+            this._disableIBus = false;
+        }
+        // If this._mruSources is not cleared before this.reload() is called,
+        // the order is different from the original one as IM sources will
+        // be appended to XKB sources.
+        this._mruSources = [];
+        this.reload();
+    },
+
     _getNewInputSource: function(current) {
         for (let i in this._inputSources) {
             let is = this._inputSources[i];